package app.gif;

import java.awt.Dimension;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageOutputStream;
import javax.imageio.stream.ImageOutputStream;

/**
 * @author Evstigneev Kirill (kester)
 */
public class FrameProcessor {

	private static final String PREVIEW_GIF = "preview.gif";
	private static final String OUT_GIF = "out.gif";

	final List<BufferedImage> frames;

	public FrameProcessor() {
		frames = new ArrayList<BufferedImage>();
	}

	public void addFrame( final BufferedImage bi ) {
		frames.add(bi);
	}

	public int getFrameCount() {
		return frames.size();
	}

	public void clear() {
		frames.clear();
	}

	private void toGif( final Integer height,
						final Integer width,
						final int framePeriod,
						final String outputPath ) {
		if(frames.size() > 0) {
			GifSequenceWriter gsw = null;
			ImageOutputStream fw = null;
			try {
				final File f = prepareDirs(OUT_GIF, outputPath);

				fw = new FileImageOutputStream(f);
				gsw = new GifSequenceWriter( fw,
  									   	 	 frames.get(0).getType(),
  									   	 	 framePeriod,
  									   	 	 true );

				for( final BufferedImage bi : frames ) {
					final BufferedImage scaledBi = resize(bi, width, height);
					gsw.writeToSequence(scaledBi);
				}
			} catch ( Exception e ) {
				e.printStackTrace();
			} finally {
				try {
					if(gsw != null)
						gsw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				try {
					if (fw != null)
						fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private File prepareDirs(final String sFileName, final String outputPath) {
		final String folderPath = outputPath;
		final File folder = new File(folderPath);
		folder.mkdirs();

		final String fileName = sFileName;
		final String pathname = File.separator.equals(folderPath.charAt(folderPath.length()-1)) ?
								folderPath + fileName :
								folderPath + File.separator + fileName;
		final File f = new File(pathname);
		return f;
	}

	private void createPreview( final String outputPath, final Integer height, final Integer width ) {
		if (frames.size() > 0) {
			ImageOutputStream fw = null;
			try {
				final File f = prepareDirs(PREVIEW_GIF, outputPath);

				fw = new FileImageOutputStream(f);
				ImageIO.write(resize(frames.get(0), width, height), "gif", fw);
			} catch ( Exception e ) {
				e.printStackTrace();
			} finally {
				if (fw != null) {
					try {
						fw.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	public void createHtmlSample() {
		if (frames.size() > 0) {
			String out = "<img res=\"" + PREVIEW_GIF + "\" + /> ";
		}
	}

	private BufferedImage resize(final BufferedImage bi, final Integer width, final Integer height) {
		Integer k = null;
		Dimension toDim = null;
		if( width == null ) {
			k = bi.getHeight() / height;
			toDim = new Dimension( bi.getWidth()/k, height);
		} else if ( height == null ) {
			k = bi.getWidth() / width;
			toDim = new Dimension( width, bi.getHeight()/k);
		} else {
			toDim = new Dimension( width, height );
		}
		final Image newImg = bi.getScaledInstance( toDim.width, toDim.height, Image.SCALE_SMOOTH );
		final BufferedImage newBufferedImage = new BufferedImage( toDim.width,
															toDim.height,
															BufferedImage.TYPE_INT_RGB );
		newBufferedImage.createGraphics().drawImage(newImg, 0, 0, null);

		return newBufferedImage;
	}

	public void toGif(final ExportProperties exportProperties) {
		toGif( exportProperties.getHeight(),
			   exportProperties.getWidth(),
			   exportProperties.getPeriod(),
			   exportProperties.getPath() );
	}

	public void createPreview(final ExportProperties exportProperties) {
		createPreview( exportProperties.getPath(),
					   exportProperties.getHeight(),
					   exportProperties.getWidth());
	}

}
